package mulMan.domain;

import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import mulMan.services.PlaylistServices;

@Entity
@Table(name = "PLAYLIST")
public class Playlist extends Observable implements Observer{
	
	private int idPlaylist;
	private String name;
	private int main;
	private Set<AudioFile> audioFiles = new ListOfAudioFiles();

	private PlaylistServices playlistServices;
	
	@Transient
	public PlaylistServices getPlaylistServices() {
		return playlistServices;
	}

	public void setPlaylistServices(PlaylistServices playlistServices) {
		this.playlistServices = playlistServices;
	}
	
	
	
	public Playlist() {
		
	}
	
	
	//Getters and Setters
	@Id
	@GeneratedValue
	@Column(name = "ID_PLAYLIST")
	public int getIdPlaylist() {
		return idPlaylist;
	}
	public void setIdPlaylist(int idPlaylist) {
		this.idPlaylist = idPlaylist;
		setChanged();

		notifyObservers("id");
	}
	@Column(name = "NAME")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
		setChanged();
		notifyObservers("name");
	}
	@Column(name = "MAIN")
	public int getMain() {
		return main;
	}
	public void setMain(int main) {
		this.main = main;
	}
	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "playlist_audio_file", joinColumns = { 
			@JoinColumn(name = "ID_PLAYLIST", nullable = false, updatable = false) }, 
			inverseJoinColumns = { @JoinColumn(name = "ID_AUDIO_FILE", 
					nullable = false, updatable = false) })
	public Set<AudioFile> getAudioFiles() {
		return ((ListOfAudioFiles) audioFiles).getAsHashSet();
	}
	public void setAudioFiles(Set<AudioFile> audioFiles) {
		this.audioFiles = new ListOfAudioFiles(audioFiles);
		
		((ListOfAudioFiles) this.audioFiles).addObserver(this);
		
		setChanged();
		notifyObservers("list");
	}
	@Transient
	public Set<AudioFile> getListOfAudioFiles() {
		return audioFiles;
	}
	
	
	public String toString() {
		return name;
	}
	@Override
	public boolean equals(Object obj) {
		boolean equals = false;
		
		if (obj instanceof Playlist) {
			if (((Playlist) obj).getIdPlaylist() == this.getIdPlaylist()) {
				equals = true;
			}
		}
		
		return equals;
	}
	@Override
	public int hashCode() {
		return 403344 * this.getIdPlaylist();
	}
	
	
	
	//Business methods
	
	public void addAudioFileToPlaylist(AudioFile audioFile) {
		audioFiles.add(audioFile);
		setChanged();
		notifyObservers("audioFile added");
		try {
			updatePlaylist();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void removeAudioFileFromPlaylist(AudioFile audioFile) {
		audioFiles.remove(audioFile);
		setChanged();
		notifyObservers("AudioFile removed");
	}

	public void savePlaylist() throws Exception {
		playlistServices.savePlaylist(this);
		setChanged();
		notifyObservers("saved");
	}

	public void updatePlaylist() throws Exception {
		playlistServices.updatePlaylist(this);
		setChanged();
		notifyObservers("updated");
	}

	public void deletePlaylist() throws Exception {
		playlistServices.deletePlaylist(this);
		setChanged();
		notifyObservers("deleted");
	}
	
	

	public void update(Observable o, Object arg) {
		if (o instanceof ListOfAudioFiles) {
			if (arg instanceof AudioFile) {
				try {
					updatePlaylist();
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				if (getName().equals("Music")) {
					try {
						((AudioFile) arg).deleteAudioFile();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}
